import http from "node:http";
import ResponseUtil from "./ResponseUtil";
import actionRegistrar from "../core/action/ActionRegistrar";
import RequestMethod, {RequestMethodType} from "./RequestMethod";
import {URLParamsObjType} from "../utils/URLUtil";
import actionInterceptorActuator from "../core/interceptor/ActionInterceptorActuator";
import actionStaticRegistrar from "../core/static/ActionStaticRegistrar";
import ActionStaticResolver from "../core/static/ActionStaticResolver";
import ActionParam from "../core/action/ActionParam";

export type RequestResultType = {
    // 请求
    request: http.IncomingMessage,
    // 请求路径
    path: string,
    // 请求对象
    URL: URL,
    // 请求方式
    method: RequestMethodType,
    // 请求参数
    params?: URLParamsObjType,
    // 请求体
    body?: string
}

class RequestParser {

    /**
     * 解析请求
     * @param {http.IncomingMessage} request 请求
     * @param {http.ServerResponse} response 响应
     * @return {Promise<ActionParam>}
     */
    parse(request: http.IncomingMessage, response: http.ServerResponse): Promise<ActionParam> {
        return new Promise((resolve, reject) => {
            try {
                if (!request) {
                    reject('Request requires request');
                }
                const actionParam = new ActionParam(request, response);

                if (actionParam.method === RequestMethod.GET || actionParam.method === RequestMethod.DELETE) {
                    resolve(actionParam)
                } else if (actionParam.method === RequestMethod.POST || actionParam.method === RequestMethod.PUT) {
                    let body = '';

                    request.on('error', err => {
                        reject(err)
                    })

                    // 接收请求体数据
                    request.on('data', chunk => {
                        // 转换为字符串
                        body += chunk.toString();
                    });

                    request.on('end', () => {
                        // 解析请求体
                        actionParam.body = body
                        resolve(actionParam)
                    });
                }
            } catch (e) {
                reject(e);
            }
        })
    }

    /**
     * 处理请求并执行处理
     * @param {ActionParam} actionParam 控制器参数
     */
    resolve(actionParam: ActionParam): Promise<any> {
        return new Promise(async (resolve, reject) => {
            // load 拦截器
            const loadInterceptorRes = actionInterceptorActuator.doLoad(actionParam);
            if (!loadInterceptorRes) {
                reject(false);
                return;
            }

            // 获取静态资源
            const staticRouteInfo = actionStaticRegistrar.get(actionParam.path)
            if (staticRouteInfo) {
                // 如果有静态资源则返回
                ActionStaticResolver.resolveAndResponse(staticRouteInfo, actionParam.response)
                reject(staticRouteInfo)
                return
            }
            // 获取路由
            const routeInfo = actionRegistrar.get(actionParam.path, actionParam.method)
            if (!routeInfo) {
                ResponseUtil.writeNotFound(actionParam.response)
                reject(false)
                return
            }
            ResponseUtil.setHeaderContentTypeText(actionParam.response)

            // before 拦截器
            const beforeInterceptorRes = actionInterceptorActuator.doBefore(actionParam, routeInfo)
            if (!beforeInterceptorRes) {
                reject(false)
                return;
            }

            // 执行处理
            let handleRes
            if (routeInfo.handle) {
                let forwardPath = ''
                actionParam.forward = (path: string) => {
                    forwardPath = path
                }
                const res = routeInfo.handle(actionParam)
                if (forwardPath) {
                    // 转发处理
                    this.resolveForward(forwardPath, actionParam.request, actionParam.response).then(res => {
                        resolve(res)
                    }).catch((e) => {
                        reject(e)
                    })
                    return
                }
                if (res instanceof Promise) {
                    handleRes = await res
                } else {
                    handleRes = res
                }
            }

            // after 拦截器
            const afterInterceptorRes = actionInterceptorActuator.doAfter(actionParam, routeInfo, handleRes)
            if (!afterInterceptorRes) {
                reject(false)
                return;
            }

            resolve(handleRes)
        })
    }

    private async resolveForward(forwardPath: string, request: http.IncomingMessage, response: http.ServerResponse) {
        const actionParam = new ActionParam(request, response);
        actionParam.isForward = true
        actionParam.path = forwardPath
        return await this.resolve(actionParam)
    }
}

export default new RequestParser();
